<?php
class gCrons {
	/**
	 * 执行计划任务
	 * @return void
	 */
	public static function work() {
	    @set_time_limit(0);
	    $maxtime = microtime(true) + max(C('CRON_MAXTIME'), 5);
	    $key = substr(md5(C('SITE_KEY').'cron'),0,8);
	    $crons = S("{$key}crons");
	    if(!is_array($crons)) {//init
	    	$crons = M('crons')->where('time<'.time())->order('level asc')->select();
	    	if(count($crons)==0) return;
	    	S("{$key}crons", $crons, 60);
	    }
	    foreach($crons as $cron_id => $cron) {
	    	$data = unserialize($cron['data']);
	    	if(!$crons[$cron_id]['done_action']) $crons[$cron_id]['done_action'] = array();
	    	//for all actions..
	    	foreach($data['actions'] as $action_id => $action) {
	    		//callable?
	    		if(!is_callable($action)) continue;
	    		//already done?
	    		if(in_array($action_id, $crons[$cron_id]['done_action'])) continue;
	    		//begin working...
	    		while(call_user_func($action)===-1) {
	    			if(microntime(true) > $maxtime) {//timeout
	    				return 'timeout';
	    			}
	    		}
	    		//done!
	    		$crons[$cron_id]['done_action'][] = $action_id;
	    		S("{$key}crons", $crons, 60);
	    	}//end of foreach actions
	    	self::complete($cron);
	    	unset($crons[$cron_id]);
	    	S("{$key}crons", $crons, 60);
	    }//end of foreach crons
		S("{$key}crons", null);
		return 'done';
	}
	private static function complete($cron) {
		$M = M('crons');
		$data = unserialize($cron['data']);
		if(!$data['repeat']) {
			$M->delete($cron['cron_id']);
			return;
		}
		switch($data['rule']) {
			case 'interval':
				$cron['time'] = time() + max($data['interval'], 60);
				$M->save($cron);
				break;
			default:
				throw_exception('CRON_UNKONWN_RULE');
				return;
		}
	}

}
?>